# Gstreamer Player file for Lsongs
#  @author Georgi Damyanov 
#
# This work is released under the GNU GPL, version 2 or later.
#
# TODO:
# Add CD and Streams Support
# Add fadein fadeout support

from qt import *
import time,re,random
from Utils.Settings import *
import warnings
from Utils.guessgenre import *
import GSTEngine
from GSTEngine import *
from CD.Ripper import *

_playerStatus = None
_currentPlayerTrack = None
_currentPlayerLibrary = None
_currentPlayerPlaylist = None
_currentPlayerVolume = 100
_currentPlayerSpeed = 100
_currentEQ = None
_eqMultiplier = 10
_eqOffset = 0
_canOverride = True
_currentPlaylists = {}
_played = False

_nextCDPlayer = "/dev/cdrom"
_prevCDPlayer = _nextCDPlayer

_parent=None
gstPlayer=None
Observer=None
warnings.filterwarnings("error",category=UserWarning)

def prev(a,b):
	a = a-1
	if a<0: a = b-1
	return a

def succ(a,b):
	a = a+1
	if a==b: a = 0
	return a

#
# a custom event used by the music player thread to communicate
# with the main thread - it's posted to the instance of
# Player
#
class GSTPlayerEvent(QCustomEvent):
	def __init__(self,status = None):
		QCustomEvent.__init__(self,QEvent.User+1)
		self._playerStatus = status
	
	def status(self):
		return self._playerStatus

def cleanPath(filePath):
	return re.sub(r"#",r"%23",filePath)

	
class GSTObserver(QThread):
	def getGSTEngine(self): return self.gstObject

	def __init__(self):
		global  gstPlayer
		QThread.__init__(self)
		gstPlayer=self.gstObject= GSTEngine()
		#gstPlayer
		self.bus=gstPlayer.getBus()
		self.started=False
	    	
	
	'''
	def onEos(self, bus, message):
	        t = message.type
		print t,"<<<<GOT MSG"
		if t == gst.MESSAGE_ERROR:
		    err, debug = message.parse_error()
		    print "Error: %s" % err, debug
		    self.started = False
		elif t == gst.MESSAGE_EOS:
		    self.emitEvent({'Status':'End','currentTime':0,'totalTime':0,'isPlaying':False,'Interrupted':False})
                    print "ZZZZZZZZZZZZZZ"
		    self.started = False
	'''
	def run(self):
		currentTime=0
		TotalTime=0
		#self.bus.enable_sync_message_emission()
		#self.bus.add_signal_watch()
	        #self.bus.connect('message', self.onEos)
		lastTime=0
		while 1:
			#print self.bus.peek(),"PEEKING"
			#print self.gstObject. getState()
			
			if self.gstObject.isReady():
				#self.emitEvent({'Status':'Begin','currentTime':0,'totalTime':0,'isPlaying':False,'Interrupted':False})
				self.msleep(200)
				#started=True
			elif self.gstObject.isPlaying():
				(currentTime,TotalTime)=self.gstObject.getPosition()
				
				if not self.started: 
					self.emitEvent({'Status':'Begin','currentTime':currentTime,'totalTime':TotalTime,'isPlaying':False,'Interrupted':False})
					self.started=True
					lastTime=0
				self.emitEvent({'Status':'Playing','currentTime':currentTime,'totalTime':TotalTime,'isPlaying':True,'Interrupted':False})

				#GTD nasty workaround for neverending stream
				if lastTime==currentTime: 
					self.emitEvent({'Status':'Next','currentTime':0,'totalTime':0,'isPlaying':False,'Interrupted':False})
					started=False
				else: lastTime=currentTime

				self.msleep(200)
			elif self.gstObject.isPaused():
				if self.gstObject.forcedPause(): self.emitEvent({'Status':'Playing','currentTime':currentTime,'totalTime':TotalTime,'isPlaying':False , 'Interrupted':True})
				else: self.emitEvent({'Status':'End','currentTime':currentTime,'totalTime':TotalTime,'isPlaying':False,'Interrupted':False})
				self.msleep(200)
			#msg=None#self.bus.poll(gst.MESSAGE_EOS | gst.MESSAGE_ERROR, gst.SECOND)
			#if msg:
			#	if started:
			#		self.emitEvent({'Status':'End','currentTime':0,'totalTime':0,'isPlaying':False,'Interrupted':False})
			#		started=False
			#	self.msleep(200)
			
#				#GTD:: currently returns always false, use when 'eos' signal problem is fixed
#				if gstObject.isEOS(): self.emitEvent({'Status':'End','currentTime':0,'totalTime':0,'isPlaying':False,'Interrupted':False})
#				else: self.emitEvent({'Status':'End','currentTime':0,'totalTime':0,'isPlaying':False,'Interrupted':True})
#				self.msleep(300)
				
	def emitEvent(self,status):
		pass
		event = GSTPlayerEvent(status)
		#Emit Signal to Player.py with status info
		QApplication.postEvent(_parent,event)

class GSTPlayer(QObject):
	def __init__(self,parent):
		global Observer
		global _parent
		_parent = parent
		QObject.__init__(self)
		GSTPlayer.gst_init()
		self.loadFromPrefs()
		#Observer=GSTObserver()
	
	def static_gst_init():
		global gstPlayer
		global Observer
		if Observer==None:
			Observer = GSTObserver()
			gstPlayer = Observer.getGSTEngine()
			gstPlayer.ready()
		return gstPlayer
	gst_init = staticmethod(static_gst_init)

	def loadFromPrefs(self):
		settings = Settings.settings()
		gstPlayer.setVolume(settings.get('Volume',50))
		self.player='gst'# settings.get('Engine','xine')
		self.setVolume(settings.get('Volume',50))
		#FIXME: implement EQ for GST
		#_eqMultiplier = settings.get("EQ Multiplier",10)
		#_eqOffset = settings.get("EQ Offset",0)
		gstPlayer.setEQ(settings.get("EQ Settings",{'On': False, 'Preamp': 0, 'Bands': [0,0,0,0,0,0,0,0,0,0]}))

	def volume(self):
		global _currentPlayerVolume
		return _currentPlayerVolume
		
	def setVolume(self,volume,fromObject = None):
		Settings.settings()['Volume'] = volume
		gstPlayer.setVolume(volume)
		self.emit(PYSIGNAL("volumeChanged"),(volume,fromObject))

	def increaseVolume(self):
		self.setVolume(min(self.volume()+10,100))

	def decreaseVolume(self):
		self.setVolume(max(self.volume()-10,0))
		
	def playTrack(self,track,library=None,playlist=None):
		global Observer
		global gstPlayer
		global _currentPlayerTrack
		global _currentPlayerLibrary
		global _currentPlayerPlaylist
		global _canOverride
		global _played
		if not Observer.running():
			print "START UP OBSERVER"
			Observer.start()
		if _currentPlayerTrack and (_currentPlayerTrack.playStatus=="playing" or _currentPlayerTrack.playStatus=="paused"):
			_currentPlayerTrack.playStatus="idle"
			
		_currentPlayerTrack = track
		_currentPlayerLibrary = library
		_currentPlayerPlaylist = playlist
		if gstPlayer.isPlaying(): gstPlayer.stop()	
		gstPlayer.play(track)
		_played = True
		
	def playerStatus(self):
		global _playerStatus
		return _playerStatus
		
	def stop(self):
		pass
		
	def killCurrentPlayer(self):
		gstPlayer.setStateNull()
		gstPlayer=None
		
	def killCurrentPlayerIfCD(self):
		global _currentPlayerTrack
		if _currentPlayerTrack and _currentPlayerTrack.kind == 'CD Track':
			self.killCurrentPlayer(self)	

	def play(self):	gstPlayer.playPause()
		
	def pause(self): gstPlayer.pause()
		
	def seek(self,time): gstPlayer.setPos(time)
	
	def killAll(self): self.killCurrentPlayer()
		
	def setCDPlayer(player):
		global _nextCDPlayer,_prevCDPlayer
		print "setCDPlayer",player
		_prevCDPlayer = _nextCDPlayer
		_nextCDPlayer = player
